package com.societyGames.flashForms
{
import com.societyGames.system.EventObject;

import flash.display.DisplayObject;
import flash.events.Event;

public class FrameOutsideContainer extends SingleItemContainer implements IChangeSize
{
  private var _desiredWidth:Number;
  private var _desiredHeight:Number;
  private var _topLeft:DisplayObject;
  private var _top:DisplayObject;
  private var _topRight:DisplayObject;
  private var _left:DisplayObject;
  private var _right:DisplayObject;
  private var _bottomLeft:DisplayObject;
  private var _bottom:DisplayObject;
  private var _bottomRight:DisplayObject;

  private var _borderTop:Number;
  private var _borderLeft:Number;
  private var _borderBottom:Number;
  private var _borderRight:Number;

  private var _sizeChangedEventObject:EventObject;

  /**
   * Adds border around an interior
   * Acts mostly like a container, but setting innerHeight/innerWidth makes it a wrapper.
   */
  public function FrameOutsideContainer(topLeft:DisplayObject, top:DisplayObject, topRight:DisplayObject, left:DisplayObject, right:DisplayObject, bottomLeft:DisplayObject, bottom:DisplayObject, bottomRight:DisplayObject)
  {
    //Make sure widths and heights line up.
    if (!haveSameHeights(topLeft, top, topRight))
    {
      throw new ArgumentError("All eight graphics must have same height and width.");
    }
    if (!haveSameHeights(bottomLeft, bottom, bottomRight))
    {
      throw new ArgumentError("All eight graphics must have same height and width.");
    }
    if (!haveSameWidths(topLeft, left, bottomLeft))
    {
      throw new ArgumentError("All eight graphics must have same height and width.");
    }
    if (!haveSameWidths(topRight, right, bottomRight))
    {
      throw new ArgumentError("All eight graphics must have same height and width.");
    }

    this._sizeChangedEventObject = new EventObject(this, "SIZE_CHANGED");
    _topLeft = topLeft;
    _topLeft.x = 0;
    _topLeft.y = 0;
    this.addChild(_topLeft);

    _top = top;
    _top.y = 0;
    this.addChild(_top);

    _topRight = topRight;
    _top.y = 0;
    this.addChild(_topRight);

    _left = left;
    _left.x = 0;
    this.addChild(_left);

    _right = right;
    this.addChild(_right);

    _bottomLeft = bottomLeft;
    _bottomLeft.x = 0;
    this.addChild(_bottomLeft);

    _bottom = bottom;
    this.addChild(_bottom);

    _bottomRight = bottomRight;
    this.addChild(_bottomRight);

    this._borderTop = _top.height;
    this._borderBottom = _bottom.height;
    this._borderRight = _right.width;
    this._borderLeft = _left.width;

    this._desiredWidth = width;
    this._desiredHeight = height;
  }

  private static function haveSameWidths(a:DisplayObject, b:DisplayObject, c:DisplayObject):Boolean
  {
    return a.width == b.width && a.width == c.width;
  }

  private static function haveSameHeights(a:DisplayObject, b:DisplayObject, c:DisplayObject):Boolean
  {
    return a.height == b.height && a.height == c.height;
  }

  public override function set width(value:Number):void
  {
    if (value != this._desiredWidth)
    {
      this._desiredWidth = value;
      recalculateWidth();
    }
  }

  private function recalculateWidth():void
  {
    var left:Number;
    var middle:Number;
    var right:Number;
    if (this._desiredWidth >= _borderLeft + _borderRight)
    {
      left = _borderLeft;
      middle = this._desiredWidth - _borderLeft - _borderRight;
      right = _borderRight;
    }
    else
    {
      left = (_borderLeft / (_borderLeft + _borderRight)) * _desiredWidth;
      middle = 0;
      right = (_borderRight / (_borderLeft + _borderRight)) * _desiredWidth;
    }
    this._topLeft.width = left;
    this._left.width = left;
    this._bottomLeft.width = left;
    this._top.x = left;
    this._top.width = middle;
    this._bottom.x = left;
    this._bottom.width = middle;
    this._topRight.x = left + middle; //this._desiredWidth - right;
    this._topRight.width = right;
    this._right.x = left + middle; //this._desiredWidth - right;
    this._right.width = right;
    this._bottomRight.x = left + middle; //this._desiredWidth - right;
    this._bottomRight.width = right;
    if (this._item != null)
    {
      this._item.width = middle;
    }
  }
  
  public override function set height(value:Number):void
  {
    if (value != this._desiredHeight)
    {
      this._desiredHeight = value;
      recalculateHeight();
    }
  }

  private function recalculateHeight():void
  {
    var top:Number;
    var middle:Number;
    var bottom:Number;
    if (this._desiredHeight >= _borderTop + _borderBottom)
    {
      top = _borderTop;
      middle = this._desiredHeight - _borderTop - _borderBottom;
      bottom = _borderBottom;
    }
    else
    {
      top = (_borderTop / (_borderTop + _borderBottom)) * _desiredHeight;
      middle = 0;
      bottom = (_borderBottom / (_borderTop + _borderBottom)) * _desiredHeight;
    }
    this._topLeft.height = top;
    this._left.y = top;
    this._left.height = middle;
    this._bottomLeft.y = this._desiredHeight - bottom;
    this._bottomLeft.height = bottom;
    this._top.height = top;
    this._bottom.y = this._desiredHeight - bottom;
    this._bottom.height = bottom;
    this._topRight.height = bottom;
    this._right.y = top;
    this._right.height = middle;
    this._bottomRight.y = this._desiredHeight - bottom;
    this._bottomRight.height = bottom;
    if (this._item != null)
    {
      this._item.height = middle;
    }
  }

  protected override function childSizeChangedHandler(event:Event):void
  {
    if (this._item != null)
    {
      this._item.x = this._borderLeft;
      this._item.y = this._borderTop;
      recalculateWidth();
      recalculateHeight();
    }
  }

  //Set space for the child.
  public function set innerWidth(value:Number):void
  {
    if (value != innerWidth)
    {
      width = value + _borderLeft + _borderRight;
      this._sizeChangedEventObject.dispatchEvent();
    }
  }

  //Get space for the child.
  public function get innerWidth():Number
  {
    return _desiredWidth - (_borderLeft + _borderRight);
  }

  //Set space for the child.
  public function set innerHeight(value:Number):void
  {
    if (value != innerHeight)
    {
      height = value + _borderBottom + _borderTop;
      this._sizeChangedEventObject.dispatchEvent();
    }
  }

  //Get space for the child.
  public function get innerHeight():Number
  {
    return _desiredHeight - (_borderBottom + _borderTop);
  }

  //IChangeSize-->
  public function get sizeChangedEventObject():EventObject
  {
    return _sizeChangedEventObject;
  }
  //<--IChangeSize
}
}